<template>
    <div class="my-map-2d" ref="container">
        <canvas ref="canvas" id="canvas"></canvas>
    </div>
</template>

<script setup lang="ts">
import { onMounted, ref, reactive } from 'vue';
import axios from 'axios'
import Cad from '@/assets/model/jx.json'
import PointPic1 from '@/assets/texture/point-1.png'
import PointPic2 from '@/assets/texture/point-2.png'
import PointPic3 from '@/assets/texture/point-3.png'
import PointPic4 from '@/assets/texture/point-4.png'
import ZhDb0 from '@/assets/texture/zh-db-0.png'
import ZhDb1 from '@/assets/texture/zh-db-1.png'
import ZhDb2 from '@/assets/texture/zh-db-2.png'
import ZhDb3 from '@/assets/texture/zh-db-3.png'
import ZhFc0 from '@/assets/texture/zh-fc-0.png'
import ZhFc1 from '@/assets/texture/zh-fc-1.png'
import ZhFc2 from '@/assets/texture/zh-fc-2.png'
import ZhFc3 from '@/assets/texture/zh-fc-3.png'
import ZhFmh0 from '@/assets/texture/zh-fmh-0.png'
import ZhFmh1 from '@/assets/texture/zh-fmh-1.png'
import ZhFmh2 from '@/assets/texture/zh-fmh-2.png'
import ZhFmh3 from '@/assets/texture/zh-fmh-3.png'
import ZhKy0 from '@/assets/texture/zh-ky-0.png'
import ZhKy1 from '@/assets/texture/zh-ky-1.png'
import ZhKy2 from '@/assets/texture/zh-ky-2.png'
import ZhKy3 from '@/assets/texture/zh-ky-3.png'
import ZhSh0 from '@/assets/texture/zh-sh-0.png'
import ZhSh1 from '@/assets/texture/zh-sh-1.png'
import ZhSh2 from '@/assets/texture/zh-sh-2.png'
import ZhSh3 from '@/assets/texture/zh-sh-3.png'
import ZhWs0 from '@/assets/texture/zh-ws-0.png'
import ZhWs1 from '@/assets/texture/zh-ws-1.png'
import ZhWs2 from '@/assets/texture/zh-ws-2.png'
import ZhWs3 from '@/assets/texture/zh-ws-3.png'
import ZhZx0 from '@/assets/texture/zh-zx-0.png'
import ZhZx1 from '@/assets/texture/zh-zx-1.png'
import ZhZx2 from '@/assets/texture/zh-zx-2.png'
import ZhZx3 from '@/assets/texture/zh-zx-3.png'
import ZhTf0 from '@/assets/texture/zh-tf-0.png'
import ZhTf1 from '@/assets/texture/zh-tf-1.png'
import ZhTf2 from '@/assets/texture/zh-tf-2.png'
import ZhTf3 from '@/assets/texture/zh-tf-3.png'


interface PointInfoParam {
    name: string,
    posX: number,
    posY: number,
    posZ: number,
    inspecType?: any, // 图标类型
    inspecStatus: number,
}

const mapCenter = [5825, 3350]
// 坐标转换
function getCadX(x: number): number {
    return (x / 0.1 + mapCenter[0])
}
function getCadY(y: number): number {
    return ((-y / 0.1) + mapCenter[1])
}

const container = ref()
const canvas = ref()

let scale = 0.1// 缩放倍数
const FIXEDSCALE = 0.1 // 初始化缩放倍数
const offset = [0, 0] // 偏移参数，x轴(正为向左 负为向右), y轴(正为向下 负为向上)
let ctx: any, width: number, height: number
// const point1 = {
//     x: 1000,
//     y: 1000
// }

// const point2 = {
//     x: 800,
//     y: 1000
// }


/**
 * 画线条
 * @param {{x:number,y:number}[]} positions 
 * @param {string} color 
 * @param {number} width 
 * @param {object} userData 
 * @return
 */
function drawLine(positions: { x: number, y: number }[] = [], color = '#fff', width = 4) {
    ctx.save()
    ctx.strokeStyle = color
    ctx.lineWidth = width * (scale / FIXEDSCALE) // 线条在缩放时保持宽度
    ctx.beginPath();
    positions.forEach((point, index) => {
        if (index === 0) {
            ctx.moveTo(cad2HtmlX(point.x), cad2HtmlY(point.y))
        } else {
            ctx.lineTo(cad2HtmlX(point.x), cad2HtmlY(point.y))
        }
    })
    ctx.stroke();
    ctx.restore();
    // 
}

/** 
 * CAD坐标转html坐标
 */
function cad2HtmlX(x: number) {
    return (x - offset[0]) * scale
}
/** 
 * CAD坐标转html坐标
 */
function cad2HtmlY(y: number) {
    return height - (y - offset[1]) * scale
}

/** 
 * html坐标转cad坐标
 */
function html2CadX(x: number) {
    return x / scale + offset[0]
}

function html2CadY(y: number) {
    return (height - y) / scale + offset[1]
}


const pointPic = [PointPic1, PointPic2, PointPic3, PointPic4]
/**
 * 放置点位置
 * @param {{name:string:posX: number, posY: number, posZ: number,inspecStatus:number,inspecType:string} } point 
 */
function putPointForWs(point: any) {
    const x = cad2HtmlX(getCadX(point.posX))
    const y = cad2HtmlY(getCadY(point.posZ))
    const div = document.createElement("div");
    div.style.position = 'absolute'
    div.style.top = y + 'px'
    div.style.left = x + 'px'
    div.style.height = '30px'
    div.style.width = 'max-content'
    div.style.backgroundRepeat = 'no-repeat'
    div.style.backgroundSize = '100% 100%'
    div.style.backgroundPosition = 'center'
    div.style.transform = 'translate(-50%,-100%)'
    div.style.fontSize = '12px'
    div.style.color = '#fff'
    div.style.paddingLeft = '5px'
    div.style.paddingRight = '5px'
    div.style.backgroundImage = 'url(' + pointPic[point.inspecStatus] + ')'
    div.style.cursor = 'default'
    div.innerText = point.name
    pointsDom.push(div)
    container.value.appendChild(div)
}


// 八大灾害图标
const zhBd = [ZhDb0, ZhDb1, ZhDb2, ZhDb3]
const zhFc = [ZhFc0, ZhFc1, ZhFc2, ZhFc3]
const zhFmh = [ZhFmh0, ZhFmh1, ZhFmh2, ZhFmh3]
const zhKy = [ZhKy0, ZhKy1, ZhKy2, ZhKy3]
const zhSh = [ZhSh0, ZhSh1, ZhSh2, ZhSh3]
const zhWs = [ZhWs0, ZhWs1, ZhWs2, ZhWs3]
const zhZx = [ZhZx0, ZhZx1, ZhZx2, ZhZx3]
const zhTf = [ZhTf0, ZhTf1, ZhTf2, ZhTf3]
/**
 * 
 * @param {{name:string:posX: number, posY: number,posZ: number,inspecStatus:number,inspecType:string}} point 
 */
function putPointForZh(point: any) {
    let object
    switch (point.inspecType) {
        case 'tf':
            object = zhTf
            break;
        case 'fc':
            object = zhFc
            break;
        case 'ws':
            object = zhWs
            break;
        case 'fmh':
            object = zhFmh
            break;
        case 'sh':
            object = zhSh
            break;
        case 'db':
            object = zhBd
            break;
        case 'ky':
            object = zhKy
            break;
        case 'zx':
            object = zhZx
            break;
        default:
            object = zhZx
            break;
    }
    const x = cad2HtmlX(getCadX(point.posX))
    const y = cad2HtmlY(getCadY(point.posZ))
    const div = document.createElement("div");
    div.style.position = 'absolute'
    div.style.top = y + 'px'
    div.style.left = x + 'px'
    div.style.height = '32px'
    div.style.width = '25px'
    div.style.backgroundRepeat = 'no-repeat'
    div.style.backgroundSize = '100% 100%'
    div.style.backgroundPosition = 'center'
    div.style.transform = 'translate(-50%,-100%)'
    div.style.cursor = 'default'
    div.style.backgroundImage = 'url(' + object[point.inspecStatus] + ')'
    div.innerHTML = `<div style="position: absolute; top:-20px; left:50%; transform: translateX(-50%); color: #fff;font-weight: 600;width: max-content;">${point.name}</div>`
    pointsDom.push(div)
    container.value.appendChild(div)

}


let mapLayer: any
/**
 * 绘制地图
 */
async function getBaseMapData() {
    mapLayer = Cad.layers[0]
    initMapData()
}
function initMapData() {
    ctx.clearRect(0, 0, width, height);
    mapLayer.lines.forEach((item: any) => {
        drawLine(item.vertices, '#18abeb', 4)
    })
}

let pointsData: any[] = []
let pointsDom: any[] = []

function getPointData(data: any[] = []) {
    // pointsData = [{
    //     "id": "1753991320500436994",
    //     "pointType": 1,
    //     "name": "张杰测试3",
    //     "posX": 75.64,
    //     "posY": 0,
    //     "posZ": 107.36,
    //     "inspecStatus": 0,
    // }, {
    //     "id": "1752890111978897410",
    //     "pointType": 1,
    //     "name": "张杰巡检点3",
    //     "posX": -70.23,
    //     "posY": 0,
    //     "posZ": 164.22,
    //     "inspecStatus": 0,
    // }]
    pointsData = data
    initPoints()
}

function initPoints() {
    pointsDom.forEach(item => {
        container.value.removeChild(item)
    })
    pointsDom = []
    pointsData.forEach(item => {
        putPointForWs(item)
    })

}


function getPointDataForZh(data: any[] = []) {
    pointsData = data
    initPointsForZh()
}
function initPointsForZh() {
    pointsDom.forEach(item => {
        container.value.removeChild(item)
    })
    pointsDom = []
    pointsData.forEach(item => {
        putPointForZh(item)
    })

}

/**
 * 移除点
 */
function removeAllPoint() {
    pointsDom.forEach(item => {
        container.value.removeChild(item)
    })
    pointsDom = []
}

/**
 * 看向点
 * @param { PointInfoParam } pointData
 */
function lookAtPoint(pointData: PointInfoParam) {
    const x = getCadX(pointData.posX)
    const y = getCadY(pointData.posZ)

    offset[0] = x - (width / 2 * scale)
    offset[1] = y - (height / 2 * scale)
    render()
}

function setInspectionPath(path: string) {
    inspectionPath = path
    initLine()
}

function initLine() {
    let path
    try {
        path = JSON.parse(inspectionPath) as any[]
    } catch (error) {
        path = []
    }
    const positions = path.map(item => {
        return {
            x: getCadX(item.x),
            y: getCadY(item.z)
        }
    })
    drawLine(positions, '#E6A23C')
}

function removeLine() {
    inspectionPath = '[]'
    render()
}
const customScale = 0.1
function handleScale(e: WheelEvent) {
    if (e.deltaY > 0) { // 放大
        if (1 / scale - customScale >= 15) return
        scale = 1 / ((1 / scale) + customScale)
        // 中心点缩放
        offset[0] -= customScale * (width / 2)
        offset[1] -= customScale * (height / 2)
    } else { // 缩小
        if (1 / scale - customScale <= 0) return
        scale = 1 / ((1 / scale) - customScale)
        offset[0] += customScale * (width / 2)
        offset[1] += customScale * (height / 2)
    }

    render()
}

function handleMove(e: MouseEvent) {
    offset[0] -= e.movementX / scale
    offset[1] += e.movementY / scale
    render()
}


const prevTouchPositions = [{ x: 0, y: 0 }, { x: 0, y: 0 }]
/**
 * 触摸移动
 * @param e 
 */
function handleTouchMove(e: TouchEvent) {
    if (e.touches.length === 1) { // 单指操作
        const movementX = prevTouchPositions[0].x - e.touches[0].clientX
        const movementY = prevTouchPositions[0].y - e.touches[0].clientY
        offset[0] += movementX / scale
        offset[1] -= movementY / scale
        render()
        setPrevTouchPositions(e)
    } else if (e.touches.length === 2) { // 双指操作
        const startA = prevTouchPositions[0].x - prevTouchPositions[1].x
        const startB = prevTouchPositions[0].y - prevTouchPositions[1].y
        const startC = Math.hypot(startA, startB)
        const currentA = e.touches[0].clientX - e.touches[1].clientX
        const currentB = e.touches[0].clientY - e.touches[1].clientY
        const currentC = Math.hypot(currentA, currentB)
        if (startC > currentC) {// 放大
            if (1 / scale - customScale >= 12) return
            scale = 1 / ((1 / scale) + customScale)
            // 中心点缩放
            offset[0] -= customScale * (width / 2)
            offset[1] -= customScale * (height / 2)
        } else {// 缩小
            if (1 / scale - customScale <= 1) return
            scale = 1 / ((1 / scale) - customScale)
            offset[0] += customScale * (width / 2)
            offset[1] += customScale * (height / 2)
        }
        render()
        setPrevTouchPositions(e)
    }
}

function setPrevTouchPositions(e: TouchEvent) {


    for (var i = 0; i < e.touches.length; i++) {
        prevTouchPositions[i].x = e.touches[i].clientX
        prevTouchPositions[i].y = e.touches[i].clientY
    }
}

/**
 * 渲染地图
 */
function render() {
    initPointsForZh()
    // initPoints()
    initMapData()
    initLine()
}

async function init() {
    const domRect = container.value.getBoundingClientRect()
    // 配置canvas的宽高
    canvas.value.width = width = domRect.width
    canvas.value.height = height = domRect.height

    ctx = canvas.value.getContext("2d")
    // 地图
    getBaseMapData()
    // 点位
    // getPointData()

    // 风量图
    // getAirData()

    // 区域
    // getAreaData()

    // 缩放
    container.value.addEventListener("wheel", handleScale)

    // 鼠标按下
    container.value.addEventListener("mousedown", function (e: MouseEvent) {
        container.value.addEventListener("mousemove", handleMove)
    })
    // 鼠标松开
    container.value.addEventListener("mouseup", function (e: MouseEvent) {
        container.value.removeEventListener("mousemove", handleMove)
    })

    // 触摸控制
    container.value.addEventListener("touchstart", function (e: TouchEvent) {
        e.preventDefault()
        setPrevTouchPositions(e)
        container.value.addEventListener("touchmove", handleTouchMove, false)

    }, false);
    container.value.addEventListener("touchend", function (e: TouchEvent) {
        container.value.removeEventListener("touchmove", handleTouchMove)
    }, false);
}

let inspectionPath: string = '[]';


onMounted(() => {
    init()
    // 巡检点
    window.$initAllpoints = getPointData
    // 巡检路线
    window.$initLine = setInspectionPath

    window.$removeLine = removeLine
    // 灾害点
    window.$initZhPoints = getPointDataForZh
    // 删除地图的点
    window.$removeAllPoint = removeAllPoint
    // 看向点位
    window.$lookAtPoint = lookAtPoint
})
</script>

<style lang="scss" scoped>
.my-map-2d {
    height: 100vh;
    position: relative;
    overflow: hidden;
    background-color: #1e232e;

    #canvas {
        // transform: scaleY(-100%);
    }

}
</style>